+git-annex (10.20250103) UNRELEASED; urgency=medium
+
+ * Improve handing of ssh connection problems during
+ remote annex.uuid discovery.
+
+ -- Joey Hess <id@joeyh.name> Fri, 03 Jan 2025 14:30:38 -0400
+
git-annex (10.20250102) upstream; urgency=medium
* Added config `url.<base>.annexInsteadOf` corresponding to git's
{- Runs a command to get the configuration of a repo,
- and returns a repo populated with the configuration, as well as the raw
- - output and the standard error of the command. -}
-fromPipe :: Repo -> String -> [CommandParam] -> ConfigStyle -> IO (Either SomeException (Repo, S.ByteString, String))
-fromPipe r cmd params st = tryNonAsync $ withCreateProcess p go
+ - output and the exit status and standard error of the command. -}
+fromPipe :: Repo -> String -> [CommandParam] -> ConfigStyle -> IO (Repo, S.ByteString, ExitCode, String)
+fromPipe r cmd params st = withCreateProcess p go
where
p = (proc cmd $ toCommand params)
{ std_out = CreatePipe
withAsync (getstderr pid herr []) $ \errreader -> do
val <- S.hGetContents hout
err <- wait errreader
- forceSuccessProcess p pid
- r' <- store val st r
- return (r', val, err)
+ exitcode <- waitForProcess pid
+ case exitcode of
+ ExitSuccess -> do
+ r' <- store val st r
+ return (r', val, exitcode, err)
+ ExitFailure _ ->
+ return (r, val, exitcode, err)
go _ _ _ _ = error "internal"
getstderr pid herr c = hGetLineUntilExitOrEOF pid herr >>= \case
{- Reads git config from a specified file and returns the repo populated
- with the configuration. -}
-fromFile :: Repo -> FilePath -> IO (Either SomeException (Repo, S.ByteString, String))
+fromFile :: Repo -> FilePath -> IO (Repo, S.ByteString, ExitCode, String)
fromFile r f = fromPipe r "git"
[ Param "config"
, Param "--file"
import qualified Data.ByteString as S
import qualified Data.ByteString.Lazy as L
import qualified System.FilePath.ByteString as P
-import Control.Exception
import Data.Default
import Annex.Common
import Logs.Remote
import Utility.Gpg
import Utility.SshHost
-import Utility.Tuple
import Utility.Directory.Create
import Messages.Progress
import Types.ProposedAccepted
getGCryptId fast r gc
| Git.repoIsLocal r || Git.repoIsLocalUnknown r = extract <$>
liftIO (catchMaybeIO $ Git.Config.read r)
- | not fast = extract . liftM fst3 <$> getM (eitherToMaybe <$>)
- [ Ssh.onRemote NoConsumeStdin r (\f p -> liftIO (Git.Config.fromPipe r f p Git.Config.ConfigList), return (Left $ giveup "configlist failed")) "configlist" [] []
- , getConfigViaRsync r gc
+ | not fast = extract <$> getM id
+ [ Ssh.onRemote NoConsumeStdin r (configpipe, return Nothing) "configlist" [] []
+ , getconfig $ getConfigViaRsync r gc
]
| otherwise = return (Nothing, r)
where
extract Nothing = (Nothing, r)
extract (Just r') = (fromConfigValue <$> Git.Config.getMaybe coreGCryptId r', r')
-getConfigViaRsync :: Git.Repo -> RemoteGitConfig -> Annex (Either SomeException (Git.Repo, S.ByteString, String))
+ configpipe f p = getconfig $ liftIO $
+ Git.Config.fromPipe r f p Git.Config.ConfigList
+
+ getconfig a = do
+ (r', _, exitcode, _) <- a
+ if exitcode == ExitSuccess
+ then return (Just r')
+ else return Nothing
+
+getConfigViaRsync :: Git.Repo -> RemoteGitConfig -> Annex (Git.Repo, S.ByteString, ExitCode, String)
getConfigViaRsync r gc = do
let (rsynctransport, rsyncurl, _) = rsyncTransport r gc
opts <- rsynctransport
| Git.repoIsSsh r = storeUpdatedRemote $ do
v <- Ssh.onRemote NoConsumeStdin r
( pipedconfig Git.Config.ConfigList autoinit (Git.repoDescribe r)
- , return (Left "configlist failed")
+ , error "internal"
)
"configlist" [] configlistfields
case v of
Right r'
| haveconfig r' -> return r'
- | otherwise -> configlist_failed
- Left _ -> configlist_failed
+ | otherwise -> do
+ configlist_failed
+ return r
+ Left exitcode -> do
+ -- ssh exits 255 when there was an error
+ -- connecting to the remote server.
+ if exitcode /= ExitFailure 255
+ then do
+ configlist_failed
+ return r
+ else do
+ warning $ UnquotedString $ "Unable to connect to repository " ++ Git.repoDescribe r ++ " to get its annex.uuid configuration."
+ return r
| Git.repoIsHttp r = storeUpdatedRemote geturlconfig
| Git.GCrypt.isEncrypted r = handlegcrypt =<< getConfigMaybe (remoteAnnexConfig r "uuid")
| Git.repoIsUrl r = do
haveconfig = not . M.null . Git.config
pipedconfig st mustincludeuuuid configloc cmd params = do
- v <- liftIO $ Git.Config.fromPipe r cmd params st
- case v of
- Right (r', val, _err) -> do
+ (r', val, exitcode, _err) <- liftIO $
+ Git.Config.fromPipe r cmd params st
+ if exitcode == ExitSuccess
+ then do
unless (isUUIDConfigured r' || val == mempty || not mustincludeuuuid) $ do
warning $ UnquotedString $ "Failed to get annex.uuid configuration of repository " ++ Git.repoDescribe r
warning $ UnquotedString $ "Instead, got: " ++ show val
warning "This is unexpected; please check the network transport!"
return $ Right r'
- Left l -> do
+ else do
warning $ UnquotedString $ "Unable to parse git config from " ++ configloc
- return $ Left (show l)
+ return $ Left exitcode
geturlconfig = Url.withUrlOptionsPromptingCreds $ \uo -> do
let url = Git.repoLocation r ++ "/config"
v <- withTmpFile "git-annex.tmp" $ \tmpfile h -> do
liftIO $ hClose h
Url.download' nullMeterUpdate Nothing url tmpfile uo >>= \case
- Right () -> pipedconfig Git.Config.ConfigNullList
- False url "git"
- [ Param "config"
- , Param "--null"
- , Param "--list"
- , Param "--file"
- , File tmpfile
- ]
+ Right () ->
+ pipedconfig Git.Config.ConfigNullList
+ False url "git"
+ [ Param "config"
+ , Param "--null"
+ , Param "--list"
+ , Param "--file"
+ , File tmpfile
+ ] >>= return . \case
+ Right r' -> Right r'
+ Left exitcode -> Left $ "git config exited " ++ show exitcode
Left err -> return (Left err)
case v of
Right r' -> do
warning $ UnquotedString $ url ++ " " ++ err
return r
- {- Is this remote just not available, or does
- - it not have git-annex-shell?
- - Find out by trying to fetch from the remote. -}
- configlist_failed = case Git.remoteName r of
- Nothing -> return r
- Just n -> do
- whenM (inRepo $ Git.Command.runBool [Param "fetch", Param "--quiet", Param n]) $ do
- set_ignore "does not have git-annex installed" True
- return r
+ configlist_failed = set_ignore "does not have git-annex installed" True
set_ignore msg longmessage = do
case Git.remoteName r of
--- /dev/null
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 1"""
+ date="2025-01-03T17:33:05Z"
+ content="""
+I don't know why ssh is failing to connect via the socket file like that.
+Generally when a socket file like this exists, there is a background ssh
+process that is servicing connections to it. It may be there was some
+problem with that process.
+
+git-annex interprets ssh failing as the ssh server not having git-annex
+installed, even though in this case it's some other problem. I have made
+some changes that improve this, so in this situation it should not set
+annex-ignore again, but will instead complain that it cannot connect to the
+server.
+"""]]